package com.ruoyi.business.youdaoController;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.protobuf.ByteString;
import com.ruoyi.business.protocol.ask.RtaApiRequestOuterClass;
import com.ruoyi.business.protocol.ask.RtaApiResponseOuterClass;
import com.ruoyi.business.services.HttpService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.enums.SaveType;
import com.ruoyi.common.utils.EncrypDES;
import com.ruoyi.common.utils.GetUrlParam;
import com.ruoyi.common.utils.OtherUtils;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.domain.vo.R;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("ownBaiDuApi")
public class BaiduController {

    @Autowired
    private RedisCache redisCache;
    @Autowired
    private HttpService httpService;

    private final static String CLASSESEN = "youdao";


    /**
     *
     * @param request
     * @return
     * @throws Exception
     */
    @Log(title = "有道", businessType = BusinessType.RTA, esIndex = "youdao_log", saveType = SaveType.ES)
    @RequestMapping(value = "/rta")
    public byte[] rtaSend(RtaApiRequestOuterClass.RtaApiRequest rtaApiRequest, HttpServletRequest request, HttpServletResponse response) throws Exception {
        String queryString = request.getQueryString();

        Map<String, Object> queryMap = GetUrlParam.queryStrToMap(queryString);
        String channelId = queryMap.get("channelId") + "";

        if(StringUtils.isBlank(channelId) || "null".equals(channelId)){
            return null;
        }
        Map<String, Object> channelDetail = redisCache.getCacheMapValue(CLASSESEN+"Cache", channelId);
        if(channelDetail == null){
            return null;
        }
        if("0".equals(channelDetail.get("isopen")+"")){
            return null;
        }

        Map<String, Object> baseParamsMap = new HashMap<>();

        long dmpid = rtaApiRequest.getQid();
        String imei = "";
        String imeiMd5 = rtaApiRequest.getDeviceInfo().getImeiMd5().toStringUtf8();
        if(StringUtils.isBlank(imeiMd5)){
            imeiMd5 = rtaApiRequest.getDeviceInfo().getImei2Md5().toStringUtf8();
        }
        //oaid
        String oaid = rtaApiRequest.getDeviceInfo().getOaid().toStringUtf8();
        //oaidMd5
        String oaidMd5 = rtaApiRequest.getDeviceInfo().getOaidMd5().toStringUtf8();
        //idfa
        String idfa = rtaApiRequest.getDeviceInfo().getIdfa().toStringUtf8();
        //idfaMd5
        String idfaMd5 = rtaApiRequest.getDeviceInfo().getIdfaMd5().toStringUtf8();
        //android_id_md5
        String androidIdMd5 = rtaApiRequest.getDeviceInfo().getAndroidIdMd5().toStringUtf8();
        //mac_md5
        String macMd5 = "";
        String caid = "";
        //sign_time,转化为秒
        long ts = rtaApiRequest.getSignTime()/1000;
        String osType = rtaApiRequest.getOsType().getValueDescriptor().getName();
        String os = "2";
        if("IOS".equals(osType)){
            os = "1";
        }else if("ANDROID".equals(osType)){
            os = "0";
        }
        //ip
        String ip = rtaApiRequest.getDeviceInfo().getUserIpV4().toStringUtf8();
        if(StringUtils.isBlank(ip)){
            ip = rtaApiRequest.getDeviceInfo().getUserIpV6().toStringUtf8();
        }
        if(StringUtils.isBlank(ip)){
            ip = IpUtils.getIpAddr(request);
        }
        String ua = request.getHeader("User-Agent");

        //将参数放入map
        baseParamsMap.put("dmpid", dmpid);
        baseParamsMap.put("request_id", dmpid);
        baseParamsMap.put("imei", imei);
        baseParamsMap.put("imei_md5", imeiMd5);
        baseParamsMap.put("oaid", oaid);
        baseParamsMap.put("oaid_md5", oaidMd5);
        baseParamsMap.put("idfa", idfa);
        baseParamsMap.put("idfa_md5", idfaMd5);
        baseParamsMap.put("android_id_md5", androidIdMd5);
        baseParamsMap.put("mac_md5", macMd5);
        baseParamsMap.put("caid", caid);
        baseParamsMap.put("ts", ts);
        baseParamsMap.put("os", os);
        baseParamsMap.put("ip", ip);
        baseParamsMap.put("ua", ua);


        String url = channelDetail.get("rta_adress") + "";
        String requestAddress = GetUrlParam.getRequestAddress(url);
        String staticParameters = GetUrlParam.TruncateUrlPage(url);
        Map<String, Object> staticParamsMap = GetUrlParam.queryStrToMap(staticParameters);
        baseParamsMap.putAll(staticParamsMap);

        List<String> tempList = new ArrayList<>();
        for(String key: baseParamsMap.keySet()){
            String value = baseParamsMap.get(key) + "";
            tempList.add(key+"="+value);
        }
        String requestParameters = String.join("&", tempList);

        long l = System.currentTimeMillis();
        String reportResultsStr = HttpUtils.sendGet(requestAddress, requestParameters, ip, ua);
        long l1 = System.currentTimeMillis();

        //baseParamsMap加入redis中
        baseParamsMap.put("reportTimeConsumption", (l1-l)+"");
        baseParamsMap.put("channelId", channelId);
        redisCache.setCacheMap(dmpid+"_Cache", baseParamsMap);

        RtaApiResponseOuterClass.RtaApiResponse.Builder builder = RtaApiResponseOuterClass.RtaApiResponse.newBuilder();
        try {
            JSONObject reportResJson = JSONObject.parseObject(reportResultsStr);
            JSONObject data = reportResJson.getJSONObject("data");
            String reqId = data.getString("request_id");
            try{
                builder.setQid(Long.parseLong(reqId));
            }catch (Exception e) {
                builder.setQid(dmpid);
            }
            String accept = data.getString("res");
            if("ALL".equals(accept)){
                builder.setRes(RtaApiResponseOuterClass.ResType.ALL);
            } else if ("PART".equals(accept)){
                builder.setRes(RtaApiResponseOuterClass.ResType.PART);
            } else if ("NONE".equals(accept)){
                builder.setRes(RtaApiResponseOuterClass.ResType.NONE);
            }
            return builder.build().toByteArray();
        }catch (Exception e){
            e.printStackTrace();
        }

        return null;
    }




    /**
     * https://www.ssptqt.com/ownBaiDuApi/send?channelId=6619838662084608&dmpid=__CLICK_ID__&req_id=__CLICK_ID__&idfa=__IDFA__&event_time_ts=__TS__&imei_md5=__IMEI_MD5__&oaid=__OAID__&oaid_md5=__OAID_MD5__&ip=__IP__&ua=__UA__&os=__OS__&callback_url=__CALLBACK_URL__&androidId=__ANDROIDID__&sign=__SIGN__
     * @param request
     * @return
     * @throws Exception
     */

    @Log(title = "有道", businessType = BusinessType.ESCALATION, esIndex = "youdao_log", saveType = SaveType.ES)
    @RequestMapping("/send")
    public Object send(HttpServletRequest request) throws Exception {
        String queryString = request.getQueryString();
        String channelId = request.getParameter("channelId");
        String dmpid = request.getParameter("dmpid");
        if(StringUtils.isBlank(channelId) || "null".equals(channelId)){
            return R.failure().msg("channelId不能为空");
        }
        if(StringUtils.isBlank(dmpid) || "null".equals(dmpid)){
            return R.failure().msg("dmpid不能为空");
        }

        Map<String, Object> baseParamsMap = GetUrlParam.queryStrToMap(queryString);

        baseParamsMap.remove("channelId");
        baseParamsMap.remove("dmpid");


        Map<String, Object> channelDetail = redisCache.getCacheMapValue(CLASSESEN+"Cache", channelId);
        if(channelDetail == null){
            return R.failure().msg("channelId不正确");
        }
        String url = channelDetail.get("request_address") + "";
        String requestType = channelDetail.get("request_type") + "";
        String requestAddress = GetUrlParam.getRequestAddress(url);
        String staticParameters = GetUrlParam.TruncateUrlPage(url);
        Map<String, Object> staticParamsMap = GetUrlParam.queryStrToMap(staticParameters);
        baseParamsMap.putAll(staticParamsMap);


        String ua = baseParamsMap.get("ua") + "";
        String ip = baseParamsMap.get("ip") + "";
        if(StringUtils.isNotBlank(ua) && !"null".equals(ua)){
            ua = URLDecoder.decode(ua, Constants.UTF8);
        }else{
            //request 获取 ua
            ua = request.getHeader("User-Agent");
            baseParamsMap.put("ua", URLEncoder.encode(ua, Constants.UTF8));
        }
        if(StringUtils.isNotBlank(ip) && !"null".equals(ip)){
        }else{
            //request 获取 ip
            ip = IpUtils.getIpAddr(request);
        }

        String callbackUrl = URLDecoder.decode(baseParamsMap.get("callback_url") + "", Constants.UTF8);
        String callbackRequestAddress = GetUrlParam.getRequestAddress(callbackUrl);
        String callbackStaticParameters = GetUrlParam.TruncateUrlPage(callbackUrl);
        callbackStaticParameters = callbackStaticParameters.replace("{{ATYPE}}", "__ATYPE__").replace("{{AVALUE}}", "__AVALUE__");

        EncrypDES encrypDES = new EncrypDES();
        String callbackBase = OtherUtils.getServerUrl(request) + "ownBaiDuApi/callback/"+ channelId +"/"+ dmpid +"/";
        String encrypt_u = encrypDES.encrypt(callbackRequestAddress);
        String nu = callbackBase + encrypt_u + "?"+callbackStaticParameters;
        //nu必须是https请求
        nu = nu.replace("http://", "https://");
        //抖音回调地址取得参数是callback
        baseParamsMap.put("callback", URLEncoder.encode(nu, Constants.UTF8));
        List<String> tempList = new ArrayList<>();
        for(String key: baseParamsMap.keySet()){
            tempList.add(key+"="+baseParamsMap.get(key));
        }
        String requestParameters = String.join("&", tempList);


        String uuid = IdUtils.fastSimpleUUID();
        String reqType = "click";
        if("POST".equals(requestType)){
            httpService.sendPost(requestAddress, requestParameters, ip, ua, uuid, reqType);
        }else{
            httpService.sendGet(requestAddress, requestParameters, ip, ua, uuid, reqType);
        }

        redisCache.setCacheMapValue(dmpid+"_Cache", "requestAddress", requestAddress);
        redisCache.setCacheMapValue(dmpid+"_Cache", "requestParameters", requestParameters);
        redisCache.setCacheMapValue(dmpid+"_Cache", "reqResultId", uuid);
        return R.success();
    }



    private String getMapValue(Map<String, Object> map, String key){
        if(map == null){
            return "";
        }
        if(map.get(key) == null){
            return "";
        }
        return map.get(key)+"";
    }


    @Log(title = "有道", businessType = BusinessType.CALLBACK, esIndex = "youdao_log", saveType = SaveType.ES)
    @RequestMapping("/callback/{channelId}/{dmpid}/{encryptedUrl}")
    public Object send(HttpServletRequest request, @PathVariable("channelId") String channelId, @PathVariable("encryptedUrl") String encryptedUrl) throws Exception {
        Map<String, Object> channelDetail = redisCache.getCacheMapValue(CLASSESEN+"Cache", channelId);
        String akey = channelDetail.get("callback_clientid") + "";

        String queryString = request.getQueryString();
        EncrypDES encrypDES = new EncrypDES();
        String requestAddress = encrypDES.decrypt(encryptedUrl);

        //获取请求参数, 并替换属性
        queryString = queryString.replace("__ATYPE__", "activate");
        queryString = queryString.replace("__AVALUE__", "0");
        String sign = DigestUtils.md5DigestAsHex((requestAddress+"?"+queryString+akey).getBytes()).toLowerCase();
        queryString = queryString + "&sign=" + sign;
        String uuid = IdUtils.fastSimpleUUID();
        String reqType = "callback";
        httpService.sendGet(requestAddress, queryString, null, null, uuid, reqType);
        return R.success();
    }

}
